package com.mew.game.core.common.handler;

import com.mew.common.dc.redis.AucRedisService;
import com.mew.common.dc.redis.EnterRoomCheckService;
import com.mew.common.dc.redis.GameRoomRedisService;
import com.mew.common.enm.ExitType;
import com.mew.common.entity.config.Game;
import com.mew.common.entity.config.Room;
import com.mew.common.exception.ResponseCode;
import com.mew.common.rest.PlayingMessage;
import com.mew.common.rest.bo.GameSession;
import com.mew.common.rest.bo.MewSession;
import com.mew.common.rest.game.EnterRoomRequest;
import com.mew.common.rest.game.EnterRoomResponse;
import com.mew.common.util.StringUtils;
import com.mew.game.core.common.messge.request.EnterGameRequestMessage;
import com.mew.game.core.common.messge.request.ReconnectionGameRequestMessage;
import com.mew.game.core.common.messge.response.EnterGameResponseMessage;
import com.mew.game.core.common.provide.GameFeignService;
import com.mew.game.core.common.utils.PushMessageUtil;
import com.zebra.common.OfflineType;
import com.zebra.common.OnlineType;
import com.zebra.remoting.config.BasisCommandCode;
import com.zebra.remoting.config.EmptyMessage;
import com.zebra.remoting.connection.Connection;
import com.zebra.remoting.tms.TmsConfigInfoManager;
import com.zebra.remoting.protocol.ZebraCommand;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;


@Service
@Slf4j
public class EnterExitRoomHandler {

    @Autowired
    private SessionManager slotsSessionManager;
    @Resource
    private GameFeignService gameFeignService;
    @Autowired
    private AucRedisService aucRedisService;
    @Autowired
    private EnterRoomCheckService enterRoomCheckService;
    @Autowired
    private GameRoomRedisService gameRoomRedisService;
    @Autowired
    private MewGameConfig mewGameConfig;



    public void enterRoom(ZebraCommand<EnterGameRequestMessage> command, MewSession session, GameSession slotsSession) {
        doEnterRoom(command, command.getRequest().getRoomId(), session, slotsSession, HandlerMapCmdType.EnterRoom);
    }

    public void reconnectRoom(ZebraCommand<ReconnectionGameRequestMessage> command, MewSession session, GameSession slotsSession) {
        ReconnectionGameRequestMessage requestMessage = command.getRequest();
        if (null == requestMessage){
            command.sendFailureCode(ResponseCode.ParamInvalid.code());
            return;
        }
        boolean check = StringUtils.checkMewStr(requestMessage.getEncryptionStr(), mewGameConfig.getLobbyKey(), mewGameConfig.getLobbyCode(), command.getToken(), requestMessage.getStartTime());
        if (!check){
            command.sendFailureCode(ResponseCode.ParamInvalid.code());
            return;
        }
        doEnterRoom(command, requestMessage.getRoomId(), session, slotsSession, HandlerMapCmdType.ReconnectRoom);
    }

    public void switchRoom(ZebraCommand<ReconnectionGameRequestMessage> command, MewSession session){
        GameSession slotsSession = new GameSession();
        ResponseCode responseCode = enterRoomCheckService.checkEnterRoom(command.getUserId(), command.getGameId(), session.rid, slotsSession);
        if (responseCode != ResponseCode.Success){
            command.sendFailureCode(responseCode.code());
            return;
        }
        buildSlotsSession(command.getChannel(), slotsSession);

        MewSession other = new MewSession();
        other.gsid = TmsConfigInfoManager.getInstance().getServerInfo().getServerId();
        aucRedisService.updateSession(session.uid, other);
    }

    private void doEnterRoom(ZebraCommand command, int roomId, MewSession session, GameSession gameSession, HandlerMapCmdType cmdType){
        if (command.getUserId() <1 || command.getGameId() <1 || roomId <1){
            command.sendFailureCode(ResponseCode.ParamInvalid.code());
            return;
        }
        if (session.checkPlaying() && session.rid != roomId){
            PlayingMessage message = gameRoomRedisService.getPlayInfo(session.gid, session.rid);
            message.setRemainTime(session.remainingLock());

            gameSession = null == gameSession ?  new GameSession() : gameSession;
            gameSession.setUserId(command.getUserId());
            gameSession.setTk(command.getToken());
            gameSession.setChannel(command.getChannel());
            PushMessageUtil.pushMessage(gameSession, BasisCommandCode.PLAYING.cmd(), message);
            return;
        }

        if (cmdType == HandlerMapCmdType.ReconnectRoom && (session.rioid == -9 || session.rid != roomId)){
            command.sendFailureCode(ResponseCode.LoginUn.code());
//            doExitRoom(command.getUserId(), ExitType.Repeat.code());
            return;
        }

        gameSession = null == gameSession ? new GameSession() : gameSession;

        ResponseCode responseCode = enterRoomCheckService.checkEnterRoom(command.getUserId(), command.getGameId(), roomId, gameSession);
        if (responseCode != ResponseCode.Success){
            command.sendFailureCode(responseCode.code());
            return;
        }

        EnterRoomResponse response;
        if (-9 == session.rioid){
            response = doFeignEnterRoom(command,  roomId, 1);
        }else {
            if (cmdType == HandlerMapCmdType.ReconnectRoom){
                response = doFeignEnterRoom(command, roomId,3);
            }else {
                response =  doFeignEnterRoom(command, roomId,2);
            }
        }

        if (ResponseCode.Success.code() != response.getErrorState()){
            log.error("Handler EnterRoom Error {}", response.toString());
            command.sendFailureCode(response.getErrorState());
            return;
        }
        //初始化 slotsSession
        buildSlotsSession(command.getChannel(), gameSession);


        EnterGameResponseMessage responseMessage = new EnterGameResponseMessage().buildData(gameSession);
        log.info("EnterRoom response : {} {}", responseMessage.toString());
        command.setToken(gameSession.getTk());
        command.sendMessage(responseMessage);
    }

    private void buildSlotsSession(Channel channel, GameSession slotsSession){
        MewSession session = aucRedisService.getSession(slotsSession.getUserId());
        slotsSession.setGameId(session.gid);
        slotsSession.setRoomId(session.rid);
        slotsSession.setChannel(channel);
        slotsSession.setTk(session.tk);
        slotsSession.setWeakClose(false);
        slotsSessionManager.put(slotsSession);
        RoomBO roomBO = RoomInfoManager.getInstance().get(slotsSession.getRoomId());
        if (null != roomBO){
            RoomInfoManager.getInstance().updateBetStr(roomBO, slotsSession.getRoomBetArray());
        }else {
            Room room = gameRoomRedisService.getRedisRoom(slotsSession.getGameId(), slotsSession.getRoomId());
            Game game = gameRoomRedisService.getRedisGame(slotsSession.getGameId());
            roomBO = RoomBO.builder()
                    .roomId(room.getId())
                    .minGoldNumber(room.getMinGoldNumber())
                    .lineNumber(game.getLineNumber())
                    .build();
            roomBO.setBetStr(room.getBetArrs());
            RoomInfoManager.getInstance().put(roomBO);
        }
    }


    private EnterRoomResponse doFeignEnterRoom(ZebraCommand command, int roomId, int type){
        Connection connection = Connection.getByChannel(command.getChannel());
        int gwId = null == connection ? -9 : connection.getServerId();

        EnterRoomRequest request = EnterRoomRequest.builder()
                .uid(command.getUserId())
                .gameId(command.getGameId())
                .roomId(roomId)
                .type(type)
                .serverId(TmsConfigInfoManager.getInstance().getServerInfo().getServerId())
                .gatewaySid(gwId)
                .build();
        EnterRoomResponse roomResponse = gameFeignService.enterRoom(request);
        return roomResponse;
    }

    /** 返回大厅 ---退出子游戏 */
    public void exitRoom(ZebraCommand command){
        gameFeignService.exitRoom(command.getUserId(), ExitType.Exit.code());
        slotsSessionManager.remove(command.getUserId());
        command.sendSuccessMsg();
    }

    public void offlineByGw(ZebraCommand<EmptyMessage> command, MewSession session, GameSession slotsSession){
        long userId = command.getUserId();
        if (null == slotsSession){
            return;
        }

        if (null == session || slotsSession.getTk() != session.tk){
            slotsSessionManager.remove(slotsSession);
            return;
        }

        if (command.getToken() != session.tk){
            return;
        }

        if (OfflineType.InactiveDiff.code() == command.getRequest().getMsg()
                || (OfflineType.Push.code() == command.getRequest().getMsg() && OnlineType.Online.value() == session.onl)){
            return;
        }

        if (OfflineType.Expired.code() == command.getRequest().getMsg()){
            gameFeignService.exitRoom(userId, ExitType.Expires.code());
        } else if (OfflineType.Repeat.code() != command.getRequest().getMsg()){
            aucRedisService.offlineSession(userId, slotsSession.getTk());
        }

        slotsSessionManager.remove(slotsSession);
    }

    //用户断线 处理
    public void offline(GameSession slotsSession){
        if (null == slotsSession){
            return;
        }
        slotsSessionManager.remove(slotsSession);
        aucRedisService.offlineSession(slotsSession.getUserId(), slotsSession.getTk());
    }


}
